﻿using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using Halk.Analyser;
using Halk.Builder;
using Halk.Config;
using Halk.Dao;
using Halk.Model;
using Halk.Utils;

namespace Halk.Spider
{
    public class NovelMover
    {
        #region 定义DAO

        /// <summary>
        /// 源article dao
        /// </summary>
        private DaoArticle _daoArticleSource;

        /// <summary>
        /// 源chapter dao
        /// </summary>
        private DaoChapter _daoChapterSource;

        ///// <summary>
        ///// 源attachs dao
        ///// </summary>
        //private DaoAttachs _daoAttachsSource;

        /// <summary>
        /// 目标article dao
        /// </summary>
        private DaoArticle _daoArticleTarget;

        /// <summary>
        /// 目标chapter dao
        /// </summary>
        private DaoChapter _daoChapterTarget;

        ///// <summary>
        ///// 目标attachs dao
        ///// </summary>
        //private DaoAttachs _daoAttachsTarget;
        
        #endregion 

        #region 定义builder

        /// <summary>
        /// html builder
        /// </summary>
        private HtmlBuilder _htmlBuilder;

        /// <summary>
        /// opf builder
        /// </summary>
        private OpfBuilder _opfBuilder;

        #endregion

        #region 定义存储变量

        /// <summary>
        /// 源书籍列表
        /// </summary>
        private IList<ArticleInfo> _articleListSource = new List<ArticleInfo>();

        /// <summary>
        /// 当前目标书籍
        /// </summary>
        private ArticleInfo _articleTarget;

        /// <summary>
        /// 目标章节列表
        /// </summary>
        private IList<ChapterInfo> _chapterListTarget = new List<ChapterInfo>();

        /// <summary>
        /// 源章节列表
        /// </summary>
        private IList<ChapterInfo> _chapterListSource = new List<ChapterInfo>();

        /// <summary>
        /// 存储最新章节信息
        /// </summary>
        private ArticleInfo _lastInfo = new ArticleInfo();

        /// <summary>
        /// 重复次数
        /// </summary>
        private int _repeatTimes;

        /// <summary>
        /// 源列表当前所处的序号
        /// </summary>
        private int _articleIndex;

        /// <summary>
        /// 分文件夹的文件大小
        /// </summary>
        private const int SizeDirectory = 1000;

        /// <summary>
        /// 存储章节分析类
        /// </summary>
        private readonly Dictionary<string, AnalyseChapter> _dicAnalyseChapter = new Dictionary<string, AnalyseChapter>();

        #endregion

        public void Work()
        {
            ConfigManage.Instace().Load();
            ContentManage.Instace().Load();
            ConfigManage.Instace().MoveFirst();
            for (var i = 0; i < ConfigManage.Instace().GetSize(); i++)
            {
                if (ConfigManage.Instace().GetConfig().IsActive.Equals(1))
                {
                    _daoArticleSource = new DaoArticle(ConfigManage.Instace().GetConfig().ConnString);
                    _daoArticleTarget = new DaoArticle(ConfigManage.Instace().GetConfig().TargetConnString);
                    _daoChapterSource = new DaoChapter(ConfigManage.Instace().GetConfig().ConnString);
                    _daoChapterTarget = new DaoChapter(ConfigManage.Instace().GetConfig().TargetConnString);
                    //_daoAttachsTarget = new DaoAttachs(ConfigManage.Instace().GetConfig().TargetConnString);

                    //初始化最大ID号
                    AppCache.Instace().MaxArticleId = _daoArticleTarget.GetArticleMaxId();
                    AppCache.Instace().MaxChapterId = _daoChapterTarget.GetChapterMaxId();
                    //AppCache.Instace().MaxAttachId = _daoAttachsTarget.GetAttachMaxID();

                    //初始化builder
                    if (_opfBuilder == null)
                        _opfBuilder = new OpfBuilder();

                    _htmlBuilder = new HtmlBuilder(ConfigManage.Instace().GetConfig());
                    _htmlBuilder.LoadDefineFile();
                    _htmlBuilder.LoadTheme();

                    GetNovelList();
                }
                ConfigManage.Instace().MoveNext();
            }
        }

        private void GetNovelList()
        {
            //获取更新时间大于记录时间的列表
            _articleListSource = _daoArticleSource.GetListByUpdateTime(ConfigManage.Instace().GetConfig().RuleFlag,
                                                                       ConfigManage.Instace().GetConfig().LastUpdate);
            if (_articleListSource.Count == 0)
            {
                System.Threading.Thread.Sleep(ConfigManage.Instace().GetConfig().SleepTimes);
                return;
            }
            _repeatTimes = 0;//重复次数置零
            for (_articleIndex = 1;//从第3本开始更新
                 _articleIndex < _articleListSource.Count &&
                 _repeatTimes < ConfigManage.Instace().GetConfig().RepeatMax &&
                 SystemManage.Instace().GetOnOff();
                 _articleIndex++)
            {
                if (!GetNovel())
                    continue;

                GetChapters();
                if (_lastInfo.lastchapterid > 0 && !string.IsNullOrEmpty(_lastInfo.lastchapter))
                {
                    _daoArticleTarget.Update(_lastInfo);
                }
                CompleteNovel();
                //更新lastchapterid lastchapter
                ConfigManage.Instace().GetConfig().LastUpdate = _articleListSource[_articleIndex].lastupdate.ToString(CultureInfo.InvariantCulture);
                ConfigManage.Instace().Save();
            }
        }

        private bool GetNovel()
        {
            _articleTarget = _daoArticleTarget.GetByName(_articleListSource[_articleIndex].articlename);
            var exists = _articleTarget.articleid != 0;
            if (!exists)
            {
                #region 赋值目标书籍

                AssignArticle(_articleListSource[_articleIndex],ref _articleTarget);
                _articleTarget.lastchapter = "";
                _articleTarget.lastchapterid = 0;
                _articleTarget.lastvolume = "";
                _articleTarget.lastvolumeid = 0;
                _articleTarget.articleid =AppCache.Instace().MaxArticleId;
                _articleTarget.postdate = TimeHelper.GetDateInt();
                _articleTarget.lastupdate = TimeHelper.GetDateInt();
                _daoArticleTarget.Add(_articleTarget);
                _lastInfo = _articleTarget;
                
                #endregion
            }
            _opfBuilder.AddMetadata(_articleTarget);
            _chapterListSource = _daoChapterSource.GetList(_articleListSource[_articleIndex].articleid,
                                                                      ConfigManage.Instace().GetConfig().RuleFlag);
            if (exists)
            {
                _chapterListTarget = _daoChapterTarget.GetList(_articleTarget.articleid);
                if (_chapterListSource.Count == _chapterListTarget.Count) //&& !_articleTarget.firstflag.Equals(1))//未匹配到最优的书籍
                {
                    _repeatTimes++;
                    ConfigManage.Instace().GetConfig().LastUpdate =
                        _articleListSource[_articleIndex].lastupdate.ToString(CultureInfo.InvariantCulture);
                    return false;
                }
            }
            else
            {
                _chapterListTarget.Clear();
                //全本下载链接
                _articleTarget.downloadlink = string.Format("{0}/files/article/txtfull/{1}/{2}.txt",
                                                            ConfigManage.Instace().GetConfig().TargetDomain,
                                                            _articleListSource[_articleIndex].articleid / SizeDirectory,
                                                            _articleListSource[_articleIndex].articleid);
            }
            if (!string.IsNullOrEmpty(_articleTarget.coverlink))
            {
                StoreCover(_articleTarget, Encoding.UTF8,ConfigManage.Instace().GetConfig().FilePath);
            }
            return true;
        }

        /// <summary>
        /// 获取该书籍的章节
        /// </summary>
        private void GetChapters()
        {
            var hasVipChapter = 0;
            var begin = _chapterListTarget.Count - 1;
            for (var ci = 0; ci < _chapterListSource.Count; ci++)
            {
                if (begin < ci) //目标站原来章节已存在
                {
                    var newChapter = new ChapterInfo();
                    AssignChapter(_chapterListSource[ci], ref newChapter);
                    _chapterListTarget.Add(newChapter);
                    _chapterListTarget[ci].articleid = _articleTarget.articleid;
                    _chapterListTarget[ci].chapterid = AppCache.Instace().MaxChapterId;
                    _chapterListTarget[ci].isnew = 1;
                    if (_chapterListTarget[ci].isvip.Equals(0) &&
                        _chapterListTarget[ci].chaptertype.Equals(0)) //章节
                    {
                        //?san
                        bool hasAttachs = false;
                        //GetChapter(_chapterListTarget[ci],ref hasAttachs); //非会员小说开始采集
                    }
                    if (_chapterListTarget[ci].chaptertype != 1 && _chapterListTarget[ci].isnew != 0)
                    {
                        #region set last info

                        _lastInfo.articleid = _chapterListTarget[ci].articleid;
                        _lastInfo.lastchapterid = _chapterListTarget[ci].chapterid;
                        _lastInfo.lastchapter = _chapterListTarget[ci].chaptername;
                        _lastInfo.lastvolumeid = _chapterListTarget[ci].volumeid;
                        _lastInfo.chapters++;

                        #endregion
                    }
                    string msg = string.Format("{0}>>{1} {2} {3} {4}",
                                         _chapterListTarget[ci].articlename,
                                         _chapterListTarget[ci].volumeid,
                                         _chapterListTarget[ci].chapterid,
                                         _chapterListTarget[ci].chapterorder,
                                         _chapterListTarget[ci].chaptername);
                    LogManage.Instace().Info(true, msg);
                    _daoChapterTarget.Add(_chapterListTarget[ci]);
                }
                if (_chapterListTarget[ci].isvip.Equals(1))
                {
                    hasVipChapter++;
                }
                _opfBuilder.AddMainfestAndSpine(_chapterListSource[ci]);
            }
            //有新增加的VIP章节或书籍未匹配到最佳
            if (hasVipChapter > 0 || _articleListSource[_articleIndex].firstflag.Equals(1))
            {
                GetVipChapters();
            }
        }
        
        /// <summary>
        /// 获取VIP章节信息
        /// </summary>
        private void GetVipChapters()
        {
            var article = _articleListSource[_articleIndex]; //源书籍
            var allChapters = _daoChapterSource.GetAllChapter(article.articleid,
                                                              ConfigManage.Instace().GetConfig().RuleFlag);
            //获取目标章节列表所有VIP章节
            var vipChapters = from p in _chapterListTarget
                              where p.chaptertype.Equals(0) && p.isvip.Equals(1) && p.isnew.Equals(1)
                              orderby p.webflag
                              select p;

            //string[] secondRule = ConfigManage.Instace().GetConfig().ReserveRules.Split(';');
            foreach (var chapter in vipChapters)
            {
                //VIP章节
                string tmpChapterName = SmartMatch.Instace().ReplaceChapterName(chapter.chaptername); //格式化章节名称
                var chapters = from item in allChapters
                               where item.articleid.Equals(article.articleid) &&
                                     tmpChapterName.Equals(SmartMatch.Instace().ReplaceChapterName(item.chaptername))
                               orderby item.webflag
                               select item;
                if (chapters.Any())
                {
                    var vipChapter = chapters.First();
                    LogManage.Instace().Info(true, string.Format("{0} VIP :{1} {2}",
                                                                       vipChapter.webflag,
                                                                       vipChapter.articlename,
                                                                       vipChapter.chaptername));
                    bool hasAttachs = false;
                    //从备用站下载TXT
                    //?san
                    //GetChapter(vipChapter, ref hasAttachs);
                    continue;
                }
                //按照章节名，在备站未找到，记录到数据库，手动操作
                _daoChapterTarget.AddMatchChapter(article.articleid, chapter);
                LogManage.Instace().Info(true, string.Format("{0}未匹配 :{1} {2}",
                                                                       chapter.webflag,
                                                                       chapter.articlename,
                                                                       chapter.chaptername));
            }
        }

        /// <summary>
        /// 下载封面
        /// </summary>
        /// <param name="article"></param>
        /// <param name="encode"></param>
        /// <param name="path"></param>
        private void StoreCover(ArticleInfo article, Encoding encode, string path)
        {
            if (string.IsNullOrEmpty(article.cover)) return;
            var cover = HttpHelper.GetImage(article.coverlink, encode);
            var link = article.cover;
            var coverPath = string.Format(@"{0}\files\article\image\{1}", path, article.articleid / 1000);
            if (!Directory.Exists(coverPath))
                Directory.CreateDirectory(coverPath);

            coverPath += string.Format(@"\{0}{1}", article.articleid, link.Substring(link.Length - 4, 4));
            cover.Save(coverPath);
        }

        /// <summary>
        /// 获取章节内容
        /// </summary>
        /// <param name="chapter"></param>
        /// <param name="hasAttachs">是否含有图片附件</param>
        public void GetChapter(ChapterInfo chapter,ref bool hasAttachs)
        {
            var analyseChapter = GetAnalyseChapter(chapter.webflag);
            analyseChapter.SetContent(HttpHelper.Get(chapter.chapterlink, analyseChapter.Encode));
            if (string.IsNullOrEmpty(analyseChapter.GetContent()))
            {
                LogManage.Instace().Error("[10002]Content is empty.");
                LogManage.Instace().Error(chapter.contentslink);
                return;
            }
            var jsTxtLink = "";
            var encoding = "";
            analyseChapter.AnalyseChapterInfo(chapter, ref jsTxtLink, ref encoding);
            if (!string.IsNullOrEmpty(jsTxtLink))
            {
                analyseChapter.ContentTxt = HttpHelper.Get(jsTxtLink, Encoding.GetEncoding(encoding));
                analyseChapter.ClearTxtMark();
            }
            if (analyseChapter.Attahcs == null || analyseChapter.Attahcs.Count == 0)//没有图片附件章节
            {
                SaveChapterTxt(chapter, analyseChapter.ContentTxt,ConfigManage.Instace().GetConfig().FilePath);
                if (chapter.ctype.Equals(1))
                {
                    chapter.ctype = 0;
                    _daoChapterTarget.Update(chapter);
                    //_daoAttachsTarget.UpdateAttachInvalid(chapter.articleid);
                }
                hasAttachs = false;
            }
            else
            {
                chapter.ctype = 1;
                _daoChapterTarget.Update(chapter);
                foreach (var attach in analyseChapter.Attahcs)
                {
                    DownloadAttach(attach);
                    //_daoAttachsTarget.Add(attach);
                }
                hasAttachs = true;
            }
        }

        /// <summary>
        /// 保存TXT文件
        /// </summary>
        /// <param name="chapter"></param>
        /// <param name="txtContent"></param>
        /// <param name="filePath"></param>
        private void SaveChapterTxt(ChapterInfo chapter, string txtContent, string filePath)
        {
            var txtPath = string.Format(@"{0}\files\article\txt\{1}\{2}", filePath, chapter.articleid / 1000,
                                        chapter.articleid);
            if (!Directory.Exists(txtPath))
                Directory.CreateDirectory(txtPath);

            txtPath += @"\" + chapter.chapterid.ToString(CultureInfo.InvariantCulture) + ".txt";
            if (!File.Exists(txtPath))
            {
                using (var sw = new StreamWriter(txtPath, false, Encoding.GetEncoding("utf-8")))
                {
                    sw.Write(txtContent);
                    sw.Close();
                }
            }
        }

        /// <summary>
        /// 下载附件
        /// </summary>
        /// <param name="attach"></param>
        private void DownloadAttach(AttachInfo attach)
        {
            var link = string.Format("{0}", attach.chapterid.ToString(CultureInfo.InvariantCulture));
        }

        /// <summary>
        /// 通过webflag获取章节分析类
        /// </summary>
        /// <param name="webflag"></param>
        /// <returns></returns>
        public AnalyseChapter GetAnalyseChapter(string webflag)
        {
            if (_dicAnalyseChapter.ContainsKey(webflag))
            {
                return _dicAnalyseChapter[webflag];
            }
            var analyseChapter = new AnalyseChapter();
            var rule = RuleManage.Instace().GetRuleFormXml(string.Format("conf/rule/{0}.xml", webflag));
            analyseChapter.Rule = rule;
            _dicAnalyseChapter[webflag] = analyseChapter;
            return analyseChapter;
        }

        /// <summary>
        /// 将书籍信息赋值
        /// </summary>
        /// <param name="source"></param>
        /// <param name="target"></param>
        private void AssignArticle(ArticleInfo source,ref ArticleInfo target)
        {
            target.articleid = source.articleid;
            target.articlename = source.articlename;
            target.articletype= source.articleid;
            target.author = source.author;
            target.chapters= source.articleid;
            target.contentslink = source.contentslink;
            target.cover = source.cover;
            target.coverlink = source.coverlink;
            target.downloadlink = source.downloadlink;
            target.firstflag= source.articleid;
            target.fullflag = source.articleid;
            target.intro = source.intro;
            target.keywords = source.keywords;
            target.lastchapter = source.lastchapter;
            target.lastchapterid = source.lastchapterid;
            target.lastupdate = source.lastupdate;
            target.lastvolume = source.lastvolume;
            target.lastvolumeid = source.lastvolumeid;
            target.sortid = source.sortid;
            target.sortname = source.sortname;
            target.size = source.size;
        }

        /// <summary>
        /// 赋值章节信息
        /// </summary>
        /// <param name="source"></param>
        /// <param name="target"></param>
        private void AssignChapter(ChapterInfo source,ref ChapterInfo target)
        {
            target.articleid = source.articleid;
            target.articlename = source.articlename;
            target.attachment = source.attachment;
            target.chapterid = source.chapterid;
            target.chapterlink = source.chapterlink;
            target.chaptername = source.chaptername;
            target.chapterorder = source.chapterorder;
            target.chaptertype = source.chaptertype;
            target.contentslink = source.contentslink;
            target.ctype = source.ctype;
            target.isnew = source.isnew;
            target.isvip = source.isvip;
            target.lastupdate = source.lastupdate;
            target.nextpage = source.nextpage;
            target.postdate = source.postdate;
            target.previewpage = source.previewpage;
            target.sourcearticleid = source.sourcearticleid;
            target.sourcechapterid = source.sourcechapterid;
            target.volumeid = source.volumeid;
            target.volumename = source.volumename;
            target.webflag = source.webflag;
        }

        /// <summary>
        /// 生成该书对应的HTML文件
        /// </summary>
        private void CompleteNovel()
        {
            if (!_opfBuilder.ConfirmOptFile(ConfigManage.Instace().GetConfig().FilePath, _articleTarget.articleid))
                return;

            _htmlBuilder.CreateIndexHtml(_articleTarget, _chapterListTarget);
            ConfigManage.Instace().GetConfig().LastUpdate = _articleListSource[_articleIndex].lastupdate.ToString(CultureInfo.InvariantCulture);
        }
    }
}
